package codec

import (
	"encoding/binary"
	"errors"
	"github.com/panjf2000/gnet/v2"
)

var ErrIncompletePacket = errors.New("incomplete packet")

type Codec struct {
	numberSize int
	bodySize   int
	body       []byte
}

func NewCodec() *Codec {
	return &Codec{
		numberSize: 4,
		bodySize:   4,
		body:       make([]byte, 0, 1024),
	}
}

func (codec *Codec) Encode(buf []byte) ([]byte, error) {
	bodyOffset := codec.numberSize + codec.bodySize
	msgLen := bodyOffset + len(buf)

	data := make([]byte, msgLen)
	//copy(data, magicNumberBytes)

	binary.BigEndian.PutUint32(data[codec.numberSize:bodyOffset], uint32(len(buf)))
	copy(data[bodyOffset:msgLen], buf)
	return data, nil
}

func (codec *Codec) Decode(c gnet.Conn) ([]byte, error) {

	bodyOffset := codec.numberSize + codec.bodySize
	buf, _ := c.Peek(bodyOffset)
	if len(buf) < bodyOffset {
		return nil, ErrIncompletePacket
	}
	//if !bytes.Equal(magicNumberBytes, buf[:magicNumberSize]) {
	//	return nil, errors.New("invalid magic number")
	//}

	bodyLen := binary.BigEndian.Uint32(buf[codec.numberSize:bodyOffset])
	msgLen := bodyOffset + int(bodyLen)
	if c.InboundBuffered() < msgLen {
		return nil, ErrIncompletePacket
	}
	buf, _ = c.Peek(msgLen)
	_, _ = c.Discard(msgLen)

	return buf[:msgLen], nil
}

func (codec *Codec) Unpack(buf []byte) ([]byte, error) {
	bodyOffset := codec.numberSize + codec.bodySize
	if len(buf) < bodyOffset {
		return nil, ErrIncompletePacket
	}

	//if !bytes.Equal(magicNumberBytes, buf[:main.magicNumberSize]) {
	//	return nil, errors.New("invalid magic number")
	//}

	bodyLen := binary.BigEndian.Uint32(buf[codec.numberSize:bodyOffset])
	msgLen := bodyOffset + int(bodyLen)
	if len(buf) < msgLen {
		return nil, ErrIncompletePacket
	}

	return buf[bodyOffset:msgLen], nil
}
